import config from '@/config';
import { Toast, Modal } from '@douyinfe/semi-ui';
import Cookies from 'js-cookie';
import store from '@/store/index.jsx';
class SharedWebSocket {
  constructor() {
    this.ws = null;
    this.reconnectAttempts = 0;
    this.maxReconnectAttempts = 5;
    this.reconnectInterval = 3000;
    this.id = null;
    this.token = null;
    this.isConnecting = false;
    this.eventListeners = new Map();
    this.isPageNavigation = false;
    this.heartbeatWorker = null;
    this.pingFailCount = 0; // ping失败计数器
    this.maxPingFailCount = 1; // 最大ping失败次数
    this.pongTimeout = null; // pong超时定时器
    this.isPingFailureReconnect = false; // 手动触发的重连
    
    // 多标签页协调相关
    this.tabId = Date.now() + Math.random().toString(36).substr(2, 9);
    this.isMainTab = false;
    this.channel = new BroadcastChannel('websocket-channel');
    
    this.setupTabCoordination();
    this.setupChannelListeners();
  }

  setupTabCoordination() {
    // 检查是否有活跃的主标签页
    const mainTabInfo = localStorage.getItem('websocket-main-tab');
    const now = Date.now();
    
    if (!mainTabInfo) {
      this.becomeMainTab();
    } else {
      try {
        const { tabId, timestamp } = JSON.parse(mainTabInfo);
        // 如果主标签页信息超过30秒，认为已失效
        if (now - timestamp > 15000) {
          this.becomeMainTab();
        }
      } catch (error) {
        this.becomeMainTab();
      }
    }
    
    // 监听localStorage变化
    window.addEventListener('storage', (e) => {
      if (e.key === 'websocket-main-tab') {
        if (!e.newValue && !this.isMainTab) {
          // 主标签页已关闭，尝试成为新的主标签页
          setTimeout(() => this.tryBecomeMainTab(), 100);
        }
      }
    });
    
    // 页面可见性变化处理
    document.addEventListener('visibilitychange', () => {
      if (document.visibilityState === 'visible' && !this.isMainTab) {
        this.checkMainTabStatus();
      }
    });
    
    // 页面关闭时清理
    window.addEventListener('beforeunload', () => {
      if (this.isMainTab) {
        localStorage.removeItem('websocket-main-tab');
        this.channel.postMessage({
          type: 'main-tab-closing',
          tabId: this.tabId
        });
      }
    });
    
    // 定期更新主标签页心跳
    if (this.isMainTab) {
      this.startMainTabHeartbeat();
    }
  }

  setupChannelListeners() {
    this.channel.onmessage = (event) => {
      const { type, data, tabId } = event.data;
      
      switch (type) {
        case 'websocket-message':
          // 接收到WebSocket消息，转发给本标签页的监听器
          this.emit('resp', data);
          break;
          
        case 'websocket-event':
          // 接收到WebSocket事件（open, close, error）
          this.emit(data.eventType, data.eventData);
          break;
          
        case 'request-connection':
          // 其他标签页请求建立连接
          if (this.isMainTab && (!this.ws || this.ws.readyState !== WebSocket.OPEN)) {
            this.connect(data.id, data.token);
          }
          break;
          
        case 'main-tab-closing':
          // 主标签页即将关闭
          if (tabId !== this.tabId) {
            setTimeout(() => this.tryBecomeMainTab(), 200);
          }
          break;
          
        case 'main-tab-heartbeat':
          // 主标签页心跳，更新时间戳
          if (tabId !== this.tabId) {
            this.lastMainTabHeartbeat = Date.now();
          }
          break;
          
        case 'ping-main-tab':
          // 检查主标签页是否活跃
          if (this.isMainTab) {
            this.channel.postMessage({
              type: 'main-tab-pong',
              tabId: this.tabId
            });
          }
          break;
          
        case 'logout-required':
          // 接收到退出登录通知
          this.handleLogout();
          break;
      }
    };
  }

  tryBecomeMainTab() {
    const mainTabInfo = localStorage.getItem('websocket-main-tab');
    if (!mainTabInfo) {
      this.becomeMainTab();
    }
  }

  becomeMainTab() {
    this.isMainTab = true;
    const tabInfo = {
      tabId: this.tabId,
      timestamp: Date.now()
    };
    localStorage.setItem('websocket-main-tab', JSON.stringify(tabInfo));
    
    // 通知其他标签页
    this.channel.postMessage({
      type: 'new-main-tab',
      tabId: this.tabId
    });
    
    // 如果有连接信息，重新建立连接
    if (this.id && this.token && (!this.ws || this.ws.readyState !== WebSocket.OPEN)) {
      this.connect(this.id, this.token);
    }
    
    this.startMainTabHeartbeat();
  }

  startMainTabHeartbeat() {
    if (this.mainTabHeartbeatInterval) {
      clearInterval(this.mainTabHeartbeatInterval);
    }
    
    this.mainTabHeartbeatInterval = setInterval(() => {
      if (this.isMainTab) {
        const tabInfo = {
          tabId: this.tabId,
          timestamp: Date.now()
        };
        localStorage.setItem('websocket-main-tab', JSON.stringify(tabInfo));
        
        this.channel.postMessage({
          type: 'main-tab-heartbeat',
          tabId: this.tabId
        });
      }
    }, 10000); // 每10秒发送一次心跳
  }

  checkMainTabStatus() {
    const mainTabInfo = localStorage.getItem('websocket-main-tab');
    if (!mainTabInfo) {
      this.tryBecomeMainTab();
      return;
    }
    
    try {
      const { timestamp } = JSON.parse(mainTabInfo);
      const now = Date.now();
      
      // 如果主标签页心跳超过30秒，尝试接管
      if (now - timestamp > 15000) {
        this.tryBecomeMainTab();
      }
    } catch (error) {
      this.tryBecomeMainTab();
    }
  }

  connect(id, token) {
    if (!id || !token) {
      return;
    }

    this.id = id;
    this.token = token;
    if (this.isMainTab) {
      this.createWebSocketConnection(id, token);
    } else {
      // 非主标签页通过BroadcastChannel请求连接
      this.channel.postMessage({
        type: 'request-connection',
        data: { id, token },
        tabId: this.tabId
      });
    }
  }

  createWebSocketConnection(id, token) {
    if (this.isConnecting) {
      console.log('WebSocket正在连接中...');
      return;
    }

    this.isConnecting = true;
    this.ws = new WebSocket(`${config.wsURL}/${id}?token=${token}`);

    this.ws.onopen = () => {
      console.log('WebSocket连接已建立');
      this.isConnecting = false;
      this.reconnectAttempts = 0;
      
      // 广播连接成功事件
      this.channel.postMessage({
        type: 'websocket-event',
        data: {
          eventType: 'open',
          eventData: { type: 'open' }
        },
        tabId: this.tabId
      });
      
      this.emit('open', { type: 'open' });
      
      // 启动心跳
      this.heartbeatWorker = new Worker(new URL('./heartbeatWorker.jsx', import.meta.url));
      this.heartbeatWorker.postMessage('start');
      this.heartbeatWorker.onmessage = (e) => {
        if (this.ws && this.ws.readyState === WebSocket.OPEN) {
          this.sendPing();
        }
      };
    };

    this.ws.onmessage = (event) => {
      try {
        if (event.data === 'pong') {
          // 收到pong响应，重置ping失败计数器
          this.pingFailCount = 0;
          if (this.pongTimeout) {
            clearTimeout(this.pongTimeout);
            this.pongTimeout = null;
          }
        } else {
          const data = JSON.parse(event.data);
          
          if (data.messageId) {
            if (data.func === 'login_out') {
              this.disconnect();
              
              // 通知所有标签页执行退出登录
              this.channel.postMessage({
                type: 'logout-required',
                tabId: this.tabId
              });
              
              // 执行本标签页的退出登录逻辑
              this.handleLogout();
              return;
            }
            this.ws.send(JSON.stringify({ func: 'ack', messageId: data.messageId }));
          }
          
          let hasHandle = Cookies.get(data.messageId);
          if (!hasHandle) {
            const expiresDate = new Date();
            expiresDate.setTime(expiresDate.getTime() + 40 * 1000);
            Cookies.set(data.messageId, data.messageId, { expires: expiresDate });
            
            // 检查是否为下载相关消息，只在主标签页处理
            const isDownloadMessage = data.func === 'export_video_success' || data.func === 'export_sub_success';
            
            if (isDownloadMessage) {
              // 下载消息只在主标签页处理，不广播到其他标签页
              if (this.isMainTab) {
                this.emit('resp', data);
              }
            } else {
              // 其他消息广播到所有标签页
              this.channel.postMessage({
                type: 'websocket-message',
                data: data,
                tabId: this.tabId
              });
              
              this.emit('resp', data);
            }
          }
        }
      } catch (error) {
        console.error('解析WebSocket消息失败:', error);
      }
    };

    this.ws.onerror = (error) => {
      console.error('WebSocket错误:', error);
      this.isConnecting = false;
      
      const errorData = { type: 'error', data: error };
      
      // 广播错误事件
      this.channel.postMessage({
        type: 'websocket-event',
        data: {
          eventType: 'error',
          eventData: errorData
        },
        tabId: this.tabId
      });
      
      this.emit('error', errorData);
    };

    this.ws.onclose = () => {
      console.log('WebSocket连接已断开');
      this.isConnecting = false;
      this.isPingFailureReconnect = false;
      // 广播关闭事件
      this.channel.postMessage({
        type: 'websocket-event',
        data: {
          eventType: 'close',
          eventData: { type: 'close' }
        },
        tabId: this.tabId
      });
      
      this.emit('close', { type: 'close' });
      this.reconnect();
    };
  }

  reconnect() {
    if (this.heartbeatWorker) {
      this.heartbeatWorker.postMessage('stop');
    }
    
    // 清理ping相关状态
    if (this.pongTimeout) {
      clearTimeout(this.pongTimeout);
      this.pongTimeout = null;
    }
    this.pingFailCount = 0;
    
    if (this.isPageNavigation) {
      this.isPageNavigation = false;
      return;
    }

    if (this.reconnectAttempts >= this.maxReconnectAttempts) {
      console.log('达到最大重连次数，停止重连');
      Modal.error({ 
        title: '提示', 
        content: '达到最大重连次数，请刷新页面', 
        hasCancel: false, 
        maskClosable: false, 
        closeOnEsc: false, 
        closable: false, 
        centered: true, 
        onOk: () => { location.reload(); } 
      });
      return;
    }

    const user = store.getState().auth.user;
    if (!user?.userId || !Cookies.get('token')) {
      return;
    }

    this.reconnectAttempts++;
    console.log(`尝试重连 (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`);
    Toast.error({ content: `服务连接已断开，正在尝试第${this.reconnectAttempts}次重连...`, stack: true });

    setTimeout(() => {
      if (this.id && this.token && this.isMainTab) {
        this.createWebSocketConnection(this.id, this.token);
      }
    }, this.reconnectInterval);
  }

  sendPing() {
    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
      this.ws.send("ping");
      
      // 设置pong超时检测（5秒内没收到pong就认为ping失败）
      if (this.pongTimeout) {
        clearTimeout(this.pongTimeout);
      }
      
      this.pongTimeout = setTimeout(() => {
        this.pingFailCount++;
        if (this.pingFailCount >= this.maxPingFailCount) {
          console.log('未收到心跳，触发重连');
          this.pingFailCount = 0;
          // 标记这是由于ping失败触发的重连，不是页面导航
          this.isPingFailureReconnect = true;
          
          // 关闭当前连接并重连
          if (this.ws) {
            this.ws.close();
            // 手动触发重连
            setTimeout(() => {
              if (this.isPingFailureReconnect) {
                this.reconnect();
              }
            }, 1000); // 1秒后如果onclose没有触发，则手动触发重连
          }
        }
      }, 5000); // 5秒超时
    }
  }

  disconnect() {
    if (this.ws) {
      this.isPageNavigation = true;
      
      // 清理ping相关定时器
      if (this.pongTimeout) {
        clearTimeout(this.pongTimeout);
        this.pongTimeout = null;
      }
      this.pingFailCount = 0;
      
      if (this.heartbeatWorker) {
        this.heartbeatWorker.postMessage('stop');
        this.heartbeatWorker.terminate();
        this.heartbeatWorker = null;
      }
      
      this.ws.close();
      this.ws = null;
      this.id = null;
      this.token = null;
      this.reconnectAttempts = 0;
      this.isConnecting = false;
      this.clearEventListeners();
    }
    
    if (this.isMainTab) {
      localStorage.removeItem('websocket-main-tab');
      this.isMainTab = false;
    }
    
    if (this.mainTabHeartbeatInterval) {
      clearInterval(this.mainTabHeartbeatInterval);
    }
  }

  sendMessageDirect(type, data) {
    if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
      console.error('WebSocket未连接');
      return false;
    }

    try {
      const message = JSON.stringify({ type, data });
      this.ws.send(message);
      return true;
    } catch (error) {
      console.error('发送消息失败:', error);
      return false;
    }
  }

  // 添加事件监听器
  on(type, callback) {
    if (!this.eventListeners.has(type)) {
      this.eventListeners.set(type, new Set());
    }
    this.eventListeners.get(type).add(callback);
  }

  // 移除事件监听器
  off(type, callback) {
    if (this.eventListeners.has(type)) {
      const listeners = this.eventListeners.get(type);
      listeners.delete(callback);
      if (listeners.size === 0) {
        this.eventListeners.delete(type);
      }
    }
  }

  // 触发事件
  emit(type, data) {
    if (this.eventListeners.has(type)) {
      this.eventListeners.get(type).forEach(callback => {
        try {
          callback(data);
        } catch (error) {
          console.error(`执行${type}事件监听器时出错:`, error);
        }
      });
    }
  }

    // 触发事件
    ohterEmit(type, data) {
        this.emit('resp', data);
        // 其他消息广播到所有标签页
        this.channel.postMessage({
          type: type,
          data: data,
          tabId: this.tabId
        });
    }

  // 清理所有事件监听器
  clearEventListeners() {
    this.eventListeners.clear();
  }

  // 处理退出登录
  handleLogout() {
    // 清除本地存储的认证信息
    Cookies.remove('token');
    Cookies.remove('user');
    
    // 清除sessionStorage中的项目相关信息
    sessionStorage.clear();
    
    // 使用 Semi Design 的 Toast 显示提示信息
    Toast.error({
      content: '登录已过期，请重新登录',
      duration: 3,
      stack: true
    });
    
    // 延迟跳转，确保用户能看到提示信息
    setTimeout(() => {
      window.location.href = '/login';
    }, 1500);
  }

  // 获取连接状态
  getConnectionStatus() {
    return {
      isMainTab: this.isMainTab,
      tabId: this.tabId,
      isConnected: this.ws && this.ws.readyState === WebSocket.OPEN,
      reconnectAttempts: this.reconnectAttempts
    };
  }
}

const sharedWebSocket = new SharedWebSocket();
export default sharedWebSocket;